package com.ustc.hewei.snowflakemodule.segment.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ustc.hewei.snowflakemodule.exception.OptimisticKeyException;
import com.ustc.hewei.snowflakemodule.segment.entity.SegmentAlloc;
import com.ustc.hewei.snowflakemodule.segment.mapper.SegmentAllocMapper;
import com.ustc.hewei.snowflakemodule.segment.service.ISegmentAllocService;
import com.ustc.hewei.snowflakemodule.util.Constants;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author hewei
 * @version 1.0
 * @description: Iservice实现
 * @date 2022/11/16 14:40
 */

@Service
public class SegmentAllocImpl extends ServiceImpl<SegmentAllocMapper, SegmentAlloc> implements ISegmentAllocService {
    @Override
    @Transactional
    public SegmentAlloc updateMaxIdAndGetAlloc(String bizTag) {
        update().eq("biz_tag", bizTag).setSql("max_id = step + max_id").update();
        return getById(bizTag);
    }

    @Override
    @Transactional
    public SegmentAlloc updateMaxIdByNewStep(String bizTag, int step) {
        update().eq("biz_tag", bizTag).setSql("max_id = max_id + " + step).update();
        return getById(bizTag);
    }

    @Override
    public SegmentAlloc updateMaxIdAndGetAllocWithOptimistic(String bizTag) throws OptimisticKeyException {
        int retried = Constants.retried;
        while (retried-- > 0) {
            SegmentAlloc pre = getById(bizTag);
            boolean isSuccess = update().eq("biz_tag", bizTag).eq("version", pre.getVersion())
                    .setSql("max_id = max_id + step").update();
            if (isSuccess) {
                pre.setMaxId(pre.getMaxId() + pre.getStep());
                return pre;
            }
        }
        throw new OptimisticKeyException("乐观锁更新maxId超出重试次数！");
    }

    @Override
    public SegmentAlloc updateMaxIdByNewStepWithOptimistic(String bizTag, int step) throws OptimisticKeyException {
        int retried = Constants.retried;
        while (retried-- > 0) {
            SegmentAlloc pre = getById(bizTag);
            boolean isSuccess = update().eq("biz_tag", bizTag).eq("version", pre.getVersion())
                    .setSql("max_id = max_id + " + step).update();
            if (isSuccess) {
                pre.setMaxId(pre.getMaxId() + step);
                return pre;
            }
        }
        throw new OptimisticKeyException("乐观锁更新maxId超出重试次数！");
    }
}
